<?php

class Reservation extends BaseReservation
{
	public static function mapStatusToText($status)
	{
		switch ($status)
		{
			case 'new': return 'Nowa';
			case 'accepted': return 'Zaakceptowana';
			case 'rejected': return 'Odrzucona';
			case 'closed': return 'Zamknięta';
		}

		return '-';
	}

	/**
	 * @param  int $hall
	 * @param  int $from
	 * @param  int $to
	 * @param  int? $excluded
	 * @return Doctrine_Collection
	 */
	public static function findOverlapping($hall, $from, $to, $excluded = null)
	{
		$q = Doctrine_Query::create()
				->from('Reservation r')
				->innerJoin('r.User')
				->where('r.hallId = :hall AND r.status <> :status', array(':hall' => (int)$hall, ':status' => 'rejected'));

		if ($excluded) $q->andWhere('r.id <> :excluded', array(':excluded' => (int)$excluded));

    return $q->andWhere(':from BETWEEN r.fromTime AND r.toTime OR :to BETWEEN r.fromTime AND r.toTime OR r.fromTime BETWEEN :from AND :to OR r.toTime BETWEEN :from AND :to', array(':from' => (int)$from, ':to' => (int)$to))->execute();
	}

	public static function createActionsFromStatus($status, $includeRead = true)
	{
		static $actions = array();

		if (isset($actions[$status]))
		{
			return $actions[$status];
		}

		$user = AgaviContext::getInstance()->getUser();
		/* @var $user SrsUser */

		$actions[$status] = array();

		if ($includeRead && $user->hasCredential('reservations.read'))
		{
			$actions[$status][] = array(
				'label' => 'Pokaż',
				'type'  => 'read',
				'route' => 'reservation.read'
			);
		}

  	switch ($status)
		{
			case 'new':
			{
				if ($user->hasCredential('reservations.edit'))
				{
					$actions[$status][] = array(
						'label' => 'Akceptuj',
						'type'  => 'accept',
						'route' => 'reservation.accept'
					);
					$actions[$status][] = array(
						'label' => 'Odrzuć',
						'type'  => 'reject',
						'route' => 'reservation.reject'
					);
				}

				break;
			}

			case 'accepted':
			{
				if ($user->hasCredential('reservations.edit'))
				{
					$actions[$status][] = array(
						'label' => 'Drukuj',
						'type'  => 'print',
						'route' => 'reservation.print'
					);
					$actions[$status][] = array(
						'label' => 'Zamknij',
						'type'  => 'close',
						'route' => 'reservation.close'
					);
				}

				break;
			}

			case 'closed':
			{
				if ($user->hasCredential('reservations.edit'))
				{
					$actions[$status][] = array(
						'label' => 'Drukuj',
						'type'  => 'print',
						'route' => 'reservation.print'
					);
				}

				break;
			}
		}

		return $actions[$status];
	}

	public function reject()
	{
		if ($this->status !== 'new')
		{
			throw new BadMethodCallException(sprintf(
				'Expected reservation with status [new], got [%s].', $this->status
			));
		}

		$this->status = 'rejected';
		$this->save();
	}

	public function accept()
	{
		if ($this->status !== 'new')
		{
			throw new BadMethodCallException(sprintf(
				'Expected reservation with status [new], got [%s].', $this->status
			));
		}

		$conn = $this->getTable()->getConnection();
		$conn->beginTransaction();

		try
		{
			$this->status = 'accepted';

			$overlappingReservations = self::findOverlapping($this->hallId, $this->fromTime, $this->toTime, $this->id);

    	foreach ($overlappingReservations as $reservation)
			{
       	$reservation->reject();
			}

			$this->save();
			
			$conn->commit();
   	}
		catch (Doctrine_Exception $x)
		{
			$conn->rollback();

			throw $x;
   	}
 	}

	public function close()
	{
		if ($this->status !== 'accepted')
		{
			throw new BadMethodCallException(sprintf(
				'Expected reservation with status [accepted], got [%s].', $this->status
			));
		}

		$this->status = 'closed';
		$this->save();
	}

	public function isAllowedToBePrinted()
	{
		return $this->status === 'closed' || $this->status === 'accepted';
	}
}